package diff;

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

/**
 * Difference between two pieces of texts.
 *  
 * @author Arseny Kapoulkine
 */
public class Diff
{
    private List packets = new ArrayList();

    /**
     * Default ctor.
     */
    public Diff()
    {
    }

    /**
     * Ctor for diff with predefined packet list.
     *
     * @param packets - packet list
     */
    public Diff(List packets)
    {
        this.packets = packets;
    }

    /**
     * Packets accessor.
     *
     * @return packet list
     */
    public List getPackets()
    {
        return packets;
    }

    /**
     * Apply diff to text.
     *
     * @param text - text to patch
     * @return resulting text
     */
    public List apply(List text)
    {
        List result = new ArrayList();

        int packetIndex = 0;
        DiffPacket packet = packetIndex < packets.size() ? (DiffPacket)packets.get(packetIndex) : null;

        for (int line = 0; line < text.size(); )
        {
            // Diffs are over
            if (packet == null)
            {
                // Ok, this can potentially be very slow - depends on subList implementation.
                result.addAll(text.subList(line, text.size()));
                break;
            }

            // Check if we have to apply diff now
            if (line < packet.start)
            {
                // We do not
                result.add(text.get(line));
                ++line;
            }
            else
            {
                // Apply diff

                // Skip relevant number of lines
                line += packet.end - packet.start;

                // Insert diff packet contents
                if (packet.contents != null) result.addAll(packet.contents);

                // Move to next packet
                ++packetIndex;
                packet = packetIndex < packets.size() ? (DiffPacket)packets.get(packetIndex) : null;
            }
        }

        return result;
    }

    /**
     * Output file to console (for debug purposes only).
     */
    public void debugPrint()
    {
        System.out.print("Diff has ");
        System.out.print(packets.size());
        System.out.println(" packets");

        for (int i = 0; i < packets.size(); ++i)
        {
            DiffPacket p = (DiffPacket)packets.get(i);

            System.out.print("Diff packet ");
            System.out.print(i);
            System.out.print(": range [");
            System.out.print(p.start);
            System.out.print(", ");
            System.out.print(p.end);
            System.out.println("), contents:");

            if (p.contents != null)
            {
                for (Iterator it = p.contents.iterator(); it.hasNext(); )
                    System.out.println((String)it.next());
            }
        }
    }

    /**
     * Calculate diff of 2 texts.
     *
     * @param source - source text
     * @param dest - destination text (applying resulting diff
     * @return calculated diff
     */
    public static Diff calculate(List source, List dest)
    {
        DiffCalculator calculator = new HuntDiffCalculator();

        return calculator.calculate(source, dest);
    }

}
